﻿/*
 * ContigousBitmapBlock
 * 
 * initial implementation : 20.10.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.IO;
//using System.Drawing;
//using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Collections.Generic;


namespace Petra.Gis.ImagingServices.Tiff
{

  /// <summary>
  /// represents block that is organized as standard bitmap
  /// where each color band alters others eg. RGBRGBRGB....
  /// </summary>
  public class ContigousBitmapBlock : BitmapBlock
  {

    //private long _blockId; //pointer to sample block on disk, this BitmapBlock will read single block
    BitmapSource _data;


    #region constructors

    /// <summary>
    /// basic constructor, creates ContigousBitmapBlock from dimensions only
    /// </summary>
    /// <param name="bounds">block position and size</param>
    /// <param name="PixelFormat">format of pixel for this block</param>
    public ContigousBitmapBlock(BlockBitmapSource parentBitmap, Int32Rect bounds, int BlockId)
      : base(parentBitmap, bounds, BlockId) { }


    ///// <summary>
    ///// creates ContigousBitmapBlock from existing bitmap
    ///// </summary>
    ///// <param name="sourceBmp"></param>
    ///// <param name="areaOfInterest"></param>
    //public ContigousBitmapBlock(BlockBitmapSource parent, BitmapSource sourceBmp, Int32Rect areaOfInterest, BitmapOperationType oType)
    //  : base(parent, areaOfInterest, oType) { }




    //public ContigousBitmapBlock(BitmapPage parent, Int32Rect bounds, int blockId)
    //  : base(parent, bounds)
    //{
    //  _blockId = blockId;

    //}

    #endregion constructors


    #region public members


    protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer)
    {
      if(_data == null)
        _data = loadData();

      _data.CopyPixels(sourceRect, buffer, bufferSize, stride);

      // if no cache requested then reset cache
      if (_parent.BitmapCacheOption == BitmapCacheOption.None)
        _data = null;
    }





    //public BitmapSource Source
    //{
    //  get
    //  {
    //    return loadData();
    //  }
    //  set
    //  {
    //    throw new NotImplementedException();
    //  }
    //}



    /// <summary>
    /// this will load data from image into block
    /// decompress if needed
    /// convert color schema if needed
    /// </summary>
    protected BitmapSource loadData()
    {
      byte[] rawDecompressedData;

      // decompress stream data as byte[]
      if (_parent.DataReader != null)
        _parent.DataReader.BaseStream.Seek(_parent.TiffMetadata.BlockOffsets[_blockId], SeekOrigin.Begin);
      else
        return null;

      rawDecompressedData = _parent.Compression.DecompressBlock(this, _parent.DataReader.ReadBytes((int)_parent.TiffMetadata.BlockLengths[_blockId]), _parent.TiffMetadata.BitsPerSamples[0]);

      
      BitmapSource data;
      //List<Color>tmpColorList;

      // covert to windows color scheme ...
      // if bilevel image then check DecodeBilevelAs8bpp
      if (_parent.TiffMetadata.PixelFormat == TiffPixelFormats.Bilevel1bpp)
      {
        if(_parent.DecodeBilevelAs8bpp)
          data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Gray8, null, rawDecompressedData, BitmapBlock.GetStrideLenght(this.PaddingWidth, 1));
        else
          data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.BlackWhite, null, rawDecompressedData, BitmapBlock.GetStrideLenght(this.PaddingWidth, 8));
      }
      else if (_parent.TiffMetadata.PixelFormat == TiffPixelFormats.Palette8bpp)
      {
        data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Indexed8, new BitmapPalette(_parent.TiffMetadata.ColorMap), rawDecompressedData, BitmapBlock.GetStrideLenght(this.PaddingWidth, 8));
      }
      else
      {
        byte[] colorConvertedData = ColorSpaceConverter.Convert(this, _parent.TiffMetadata.PixelFormat, PixelFormats.Rgb24);
        //data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Rgb24, null, colorConvertedData, BitmapBlock.GetStrideLenght(_bounds.Width, PixelFormats.Rgb24.BitsPerPixel));
        data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Rgb24, null, colorConvertedData, BitmapBlock.GetStrideLenght(this.PaddingWidth, PixelFormats.Rgb24.BitsPerPixel));
      }

      return data;
    }




    ///// <summary>
    ///// returns (compressed) size of current stripe or tile in bytes
    ///// </summary>
    //public int CompressedSize
    //{
    //  get 
    //  {
    //    if (_image.Metadata.IsTiled)
    //      return System.Convert.ToInt32(_image.Metadata.Ifd.GetTag(TagType.TILEBYTECOUNTS).TagData[_blockIndex]);
    //    else
    //      return System.Convert.ToInt32(_image.Metadata.Ifd.GetTag(TagType.STRIPBYTECOUNTS).TagData[_blockIndex]);
    //  }
    //}


    #endregion public members


  }
}
